package demo3;

import java.util.Scanner;
// 银行家算法类
public class BankersAlgorithm {
    private Process[] processes;
    private Resource resource;
    private int numResources;
    private int numProcesses;

    public BankersAlgorithm(int numProcesses, int numResources) {
        this.numProcesses = numProcesses;
        this.numResources = numResources;
        processes = new Process[numProcesses];
        for (int i = 0; i < numProcesses; i++) {
            processes[i] = new Process(i, numResources);
        }
        resource = new Resource(numResources);
    }

    // 初始化数据
    public void initialize() {
        Scanner scanner = new Scanner(System.in);

        // 输入可用资源
        System.out.println("输入" + numResources + "种可用资源数量:");
        int[] available = new int[numResources];
        for (int i = 0; i < numResources; i++) {
            available[i] = scanner.nextInt();
        }
        resource.setAvailable(available);

        // 输入每个进程的最大需求和已分配资源
        for (int i = 0; i < numProcesses; i++) {
            System.out.println("进程 " + i + ":");

            System.out.println("输入最大需求:");
            int[] max = new int[numResources];
            for (int j = 0; j < numResources; j++) {
                max[j] = scanner.nextInt();
            }
            processes[i].setMax(max);

            System.out.println("输入已分配资源:");
            int[] allocation = new int[numResources];
            for (int j = 0; j < numResources; j++) {
                allocation[j] = scanner.nextInt();
            }
            processes[i].setAllocation(allocation);

            // 计算需求向量
            processes[i].calculateNeed();
        }
    }

    // 安全性算法，检查系统是否处于安全状态
    public boolean isSafe() {
        int[] work = resource.getAvailable().clone(); // 工作向量
        boolean[] finish = new boolean[numProcesses]; // 完成标志
        int[] safeSequence = new int[numProcesses]; // 安全序列
        int count = 0;

        // 寻找安全序列
        while (count < numProcesses) {
            boolean found = false;
            for (int i = 0; i < numProcesses; i++) {
                if (!finish[i]) {
                    // 检查需求是否小于等于可用资源
                    boolean canAllocate = true;
                    for (int j = 0; j < numResources; j++) {
                        if (processes[i].getNeed()[j] > work[j]) {
                            canAllocate = false;
                            break;
                        }
                    }

                    // 如果可以分配，假设该进程完成并释放资源
                    if (canAllocate) {
                        for (int j = 0; j < numResources; j++) {
                            work[j] += processes[i].getAllocation()[j];
                        }
                        safeSequence[count++] = i;
                        finish[i] = true;
                        found = true;
                    }
                }
            }

            // 如果没有找到可分配的进程，系统不安全
            if (!found) {
                System.out.println("系统处于不安全状态");
                return false;
            }
        }

        // 输出安全序列
        System.out.println("系统处于安全状态，安全序列为:");
        for (int i = 0; i < numProcesses; i++) {
            System.out.print("P" + safeSequence[i] + " ");
        }
        System.out.println();
        return true;
    }

    // 请求资源
    public void requestResources(int processId, int[] request) {
        // 检查请求是否合法
        Process p = processes[processId];
        boolean valid = true;

        // 检查请求是否超过需求
        for (int i = 0; i < numResources; i++) {
            if (request[i] > p.getNeed()[i]) {
                valid = false;
                System.out.println("错误: 请求超过最大需求");
                break;
            }
        }

        // 检查请求是否超过可用资源
        if (valid) {
            for (int i = 0; i < numResources; i++) {
                if (request[i] > resource.getAvailable()[i]) {
                    valid = false;
                    System.out.println("错误: 可用资源不足，进程需等待");
                    break;
                }
            }
        }

        // 如果请求合法，尝试分配
        if (valid) {
            // 临时分配资源
            for (int i = 0; i < numResources; i++) {
                resource.getAvailable()[i] -= request[i];
                p.getAllocation()[i] += request[i];
                p.getNeed()[i] -= request[i];
            }

            // 检查分配后系统是否安全
            if (isSafe()) {
                System.out.println("资源分配成功");
            } else {
                // 不安全则回滚分配
                System.out.println("资源分配会导致系统不安全，取消分配");
                for (int i = 0; i < numResources; i++) {
                    resource.getAvailable()[i] += request[i];
                    p.getAllocation()[i] -= request[i];
                    p.getNeed()[i] += request[i];
                }
            }
        }
    }

    // 显示系统状态
    public void displaySystemState() {
        resource.display();
        for (Process p : processes) {
            p.display();
        }
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        System.out.println("===== 银行家算法模拟 =====");
        System.out.print("输入进程数量: ");
        int numProcesses = scanner.nextInt();
        System.out.print("输入资源种类数量: ");
        int numResources = scanner.nextInt();

        BankersAlgorithm ba = new BankersAlgorithm(numProcesses, numResources);
        ba.initialize();

        System.out.println("\n初始系统状态:");
        ba.displaySystemState();

        // 检查初始状态是否安全
        System.out.println("\n检查初始状态安全性:");
        ba.isSafe();

        // 处理资源请求
        while (true) {
            System.out.println("\n是否请求资源? (1-是, 0-否): ");
            int choice = scanner.nextInt();
            if (choice == 0) break;

            System.out.print("输入请求资源的进程ID: ");
            int processId = scanner.nextInt();

            System.out.println("输入请求的资源数量:");
            int[] request = new int[numResources];
            for (int i = 0; i < numResources; i++) {
                request[i] = scanner.nextInt();
            }

            ba.requestResources(processId, request);
            System.out.println("\n当前系统状态:");
            ba.displaySystemState();
        }

        scanner.close();
    }
}